﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using diploma.core;
using diploma.core.data;
using diploma.core.localize;
using diploma.test.core;

namespace diploma.test.GUI
{

    public partial class TestControl : UserControl, ILocalizable
    {
        private List<Question> questions;
        private int questionNumber = -1;
        private AbstractLocalizator localizator;
        private Dictionary<DataObjectTypes, DataList<diploma.core.data.IDataObject>> collection;

        public TestControl(AbstractLocalizator _localizator, Dictionary<DataObjectTypes, DataList<diploma.core.data.IDataObject>> _collection)
        {
            collection = _collection;
            InitializeComponent();
            localizator = _localizator;
            Localize();
            test();
        }

        private void test()
        {
            // questions = new List<Question>(TestManager.Instance.MakeTest(collection));
            questions = new List<Question>();
            questions.Add(new SingleQuestion("Назовіть значення властивості  B для об’єкта А,\r\n де А – tgx, B – найм. полозитивний період", "П", new string[] { "2П", "П", "немає" }));
            questions.Add(new ExactQuestion("Як назиывається твердження, яке не потребує доказу?", "аксіома"));
            questions.Add(new DifficultQuestion("Які об’єкти мають значення властивості A? \r\n де А – парність: непарна", new string[] { "sinx", "arcsinx" }, new string[] { "arcsinx", "cosx", "arctgx", "sinx" }));
            questions.Add(new TermQuestion(localizator.GetLocolizeWord("fill_terms"), "з кожної обмеженої послідовності точок простору можливо виділити збіжну підпослідовність", collection[DataObjectTypes.Term], 2));
            if (questions.Count > 0)
            {
                questionNumber = 0;
            }

            lProgress.Text = "0/" + questions.Count;
            NextQuestion(null, null);
        }

        private bool ArraysEqual<T>(T[] a1, T[] a2)
        {
            if (ReferenceEquals(a1, a2))
                return true;

            if (a1 == null || a2 == null)
                return false;

            if (a1.Length != a2.Length)
                return false;

            EqualityComparer<T> comparer = EqualityComparer<T>.Default;
            for (int i = 0; i < a1.Length; i++)
            {
                if (!comparer.Equals(a1[i], a2[i])) return false;
            }
            return true;
        }


        private void ClearTestPanel()
        {
            if (pTestItem.HasChildren)
            {
                pTestItem.Controls.Clear();
            }
        }

        private void NextQuestion(object sender, EventArgs e)
        {
            if (questions.Count > 0 && questionNumber < questions.Count)
            {
                if (questionNumber > 0)
                {
                    checkAnswer(questions[questionNumber - 1]);
                }
                ClearTestPanel();
                lQuestion.Text = "" + (questionNumber + 1) + ". ";
                switch (questions[questionNumber].Type)
                {
                    case QuestionTypes.Single:
                        buildSingleQuestion(questions[questionNumber]);
                        break;
                    case QuestionTypes.Difficult:
                        buildDifficultQuestion(questions[questionNumber]);
                        break;
                    case QuestionTypes.Exact:
                        buildExactQuestion(questions[questionNumber]);
                        break;
                    case QuestionTypes.Complex:
                        buildComplexQuestion(questions[questionNumber]);
                        break;
                    case QuestionTypes.Term:
                        buildTermQuestion(questions[questionNumber]);
                        break;
                    case QuestionTypes.Binds:
                        buildBindsQuestion(questions[questionNumber]);
                        break;
                    case QuestionTypes.Undefined:
                    default:
                        Console.WriteLine("Trouble! Question is undefined");
                        break;
                }
                questionNumber++;
            }
            else
            {

                if (questionNumber == questions.Count)
                {
                    checkAnswer(questions[questionNumber - 1]);
                    ClearTestPanel();
                    lQuestion.Hide();
                    lRight.Hide();
                    lProgress.Hide();
                    btnNext.Hide();
                    Label lResult = new Label();
                    lResult.Text = localizator.GetLocolizeWord("right_answers");
                    lResult.Text += "" + right;
                    lResult.AutoSize = true;
                    Label lFailed = new Label();
                    lFailed.AutoSize = true;
                    lFailed.Text = localizator.GetLocolizeWord("failed_answers");
                    lFailed.Text += "" + failed;
                    lFailed.Top = lResult.Height;
                    Label lMark = new Label();
                    lMark.AutoSize = true;
                    lMark.Top = lFailed.Top + lFailed.Height;
                    double p = ((double)right / (double)questions.Count) * 100;
                    string mark = "";
                    if (p <= 100 && p >= 90) mark = "A";
                    if (p >= 75 && p < 90) mark = "BC";
                    if (p >= 60 && p < 75) mark = "DE";
                    if (p < 60) mark = "FX";
                    lMark.Text = localizator.GetLocolizeWord("percents") + p + "% " + localizator.GetLocolizeWord("your_mark") + mark;
                    pTestItem.Controls.Add(lResult);
                    pTestItem.Controls.Add(lFailed);
                    pTestItem.Controls.Add(lMark);
                }
            }
        }

        private int right = 0;
        private int failed = 0;

        public void RefreshPanel()
        {
            lProgress.Show();
            lProgress.Text = "0/" + questions.Count;
            lQuestion.Show();
            lRight.Show();
            btnNext.Show();
            right = 0;
            failed = 0;
            test();
        }

        private void checkAnswer(Question _q)
        {
            switch (_q.Type)
            {
                case QuestionTypes.Single:
                    bool isChanged = false;
                    SingleQuestion q1 = _q as SingleQuestion;
                    for (int i = 0; i < q1.Options.Length; i++)
                    {
                        RadioButton tmp = (pTestItem.Controls["Option" + i] as RadioButton);
                        if (tmp.Checked)
                        {
                            if (i == q1.RightOption)
                            {
                                right++;

                            }
                            else
                            {
                                failed++;

                            }
                            isChanged = true;
                            break;
                        }
                    }
                    if (!isChanged) failed++;
                    break;
                case QuestionTypes.Binds:
                    break;
                case QuestionTypes.Complex:
                    break;
                case QuestionTypes.Difficult:
                    DifficultQuestion q4 = _q as DifficultQuestion;
                    List<int> answers = new List<int>();
                    for (int i = 0; i < q4.Options.Length; i++)
                    {
                        CheckBox tmp = (pTestItem.Controls["Option" + i] as CheckBox);
                        if (tmp.Checked) answers.Add(i);
                    }
                    answers.Sort();
                    if (ArraysEqual<int>(answers.ToArray(), q4.RightOptions))
                    {
                        right++;
                    }
                    else
                    {
                        failed++;
                    }
                    break;
                case QuestionTypes.Exact:
                    ExactQuestion q5 = _q as ExactQuestion;
                    if (pTestItem.Controls["Exact"].Text == q5.RightAnswer)
                    {
                        right++;
                    }
                    else
                    {
                        failed++;
                    }
                    break;
                case QuestionTypes.Term:
                    TermQuestion q6 = _q as TermQuestion;
                    List<string> terms = new List<string>();
                    for (int i = 0; i < q6.TermCount; i++)
                    {
                        terms.Add(pTestItem.Controls["Term" + i].Text.Trim());
                    }
                    if (ArraysEqual<string>(terms.ToArray(), q6.RightAnswer))
                    {
                        right++;
                    }
                    else
                    {
                        failed++;
                    }
                    break;
                case QuestionTypes.Undefined:
                default:
                    break;
            }
            lProgress.Text = "" + right + "/" + questions.Count;
        }

        private void buildSingleQuestion(Question _question)
        {
            SingleQuestion q = _question as SingleQuestion;
            if (q != null)
            {
                lQuestion.Text += q.QuestionDescription;
                int i = 0;
                foreach (string option in q.Options)
                {
                    RadioButton rb = new RadioButton();
                    rb.Name = "Option" + i;
                    rb.Text = option;
                    rb.AutoSize = true;
                    rb.Height = 20;
                    rb.Top = rb.Height + 20 * i;
                    pTestItem.Controls.Add(rb);
                    i++;
                }

            }
        }

        private void buildDifficultQuestion(Question _question)
        {
            DifficultQuestion q = _question as DifficultQuestion;
            if (q != null)
            {
                lQuestion.Text += q.QuestionDescription;
                int i = 0;
                foreach (string option in q.Options)
                {
                    CheckBox cb = new CheckBox();
                    cb.Name = "Option" + i;
                    cb.Text = option;
                    cb.AutoSize = true;
                    cb.Height = 20;
                    cb.Top = cb.Height + 20 * i;
                    pTestItem.Controls.Add(cb);
                    i++;
                }
            }
        }

        private void buildBindsQuestion(Question _question)
        {
            BindsQuestion q = _question as BindsQuestion;
            if (q != null)
            {
                lQuestion.Text += q.QuestionDescription;

            }
        }

        private void buildTermQuestion(Question _question)
        {
            TermQuestion q = _question as TermQuestion;
            if (q != null)
            {
                lQuestion.Text += q.QuestionDescription;
                System.Windows.Forms.Label l = new Label();

                l.Width = pTestItem.Width - 20;
                l.Height = 50;
                l.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
                l.Text = q.Term;
                pTestItem.Controls.Add(l);
                for (int i = 0; i < q.TermCount; i++)
                {
                    TextBox tmp = new TextBox();

                    Label ltmp = new Label();
                    ltmp.Height = 20;
                    ltmp.Width = 20;
                    ltmp.AutoSize = true;
                    ltmp.Text = "" + (i + 1);

                    tmp.Height = 20;
                    tmp.Left = ltmp.Width + 10;

                    ltmp.Top = 55 + tmp.Height + tmp.Height * i;
                    tmp.Top = 55 + tmp.Height + tmp.Height * i;
                    tmp.Name = "Term" + i;
                    pTestItem.Controls.Add(ltmp);
                    pTestItem.Controls.Add(tmp);
                    tmp.Show();
                    ltmp.Show();
                }

            }
        }

        private void buildComplexQuestion(Question _question)
        {
            ComplexQuestion q = _question as ComplexQuestion;
            if (q != null)
            {
                lQuestion.Text += q.QuestionDescription;
                System.Windows.Forms.RichTextBox rtb = new RichTextBox();
                rtb.Width = pTestItem.Width - 20;
                rtb.Height = pTestItem.Height - 20;
                rtb.Anchor = AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
                pTestItem.Controls.Add(rtb);
            }
        }

        private void buildExactQuestion(Question _question)
        {
            ExactQuestion q = _question as ExactQuestion;
            if (q != null)
            {
                lQuestion.Text += q.QuestionDescription;
                System.Windows.Forms.TextBox tb = new TextBox();
                tb.Width = 100;
                tb.Height = 20;
                tb.Name = "Exact";
                tb.Anchor = AnchorStyles.Left | AnchorStyles.Top;
                pTestItem.Controls.Add(tb);
            }
        }

        #region ILocalizable Members

        public void Localize()
        {
            lQuestion.Text = localizator.GetLocolizeWord(lQuestion.Text);
            btnNext.Text = localizator.GetLocolizeWord(btnNext.Text);
            lRight.Text = localizator.GetLocolizeWord(lRight.Text);
        }

        #endregion
    }
}
